/*
 * Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

 #include <mutex>
#include <signal.h>
 #include "timer_mgr.h"
 #include "iot_connect_log.h"
 #include "reply_handler.h"
 #include "cJSON.h"

namespace OHOS {
namespace iotConnect {
std::mutex TimerMgr::mutex_;
uint64_t TimerMgr::msgSeq = 0;
std::unordered_map<uint64_t, MessageTimerAttr*> TimerMgr::um_timers_ = {};
TimerMgr* TimerMgr::GetInstance()
{
    static TimerMgr timer;
    return &timer;
}

void TimerMgr::SubThingModelWaitReply(const IotcCharState& state)
{
#if IOTC_CONF_DEV_TYPE == 2
    uint32_t ret = 0;
    struct sigevent sev;
    struct itimerspec its;
    MessageTimerAttr* mess_attr = new MessageTimerAttr;
    mess_attr->msgSeq = msgSeq;
    mess_attr->devId = state.devId;
    mess_attr->svcId = state.svcId;
    mess_attr->onResult = ReplyHandler::SubThingModelReplyHandler;
    sev.sigev_notify = SIGEV_THREAD;
    sev.sigev_notify_function = this->SubThingModelTimeroutHandler;
    sev.sigev_notify_attributes = nullptr;
    sev.sigev_value.sival_ptr = mess_attr;

    timer_t timer_id;
    ret = timer_create(CLOCK_REALTIME, &sev, &timer_id);
    if(-1 == ret) {
        HILOGE("timer_create error, ret: %{public}d", ret);
        delete mess_attr;
        return;
    }

    mess_attr->timerId = timer_id;

    its.it_value.tv_sec = timeout_;
    its.it_value.tv_nsec = 0;
    its.it_interval.tv_sec = 0;
    its.it_interval.tv_nsec = 0;

    ret = timer_settime(timer_id, 0, &its, nullptr);
    if(-1 == ret) {
        HILOGE("timer_settime error, ret: %{public}d", ret);
        delete mess_attr;
        return;
    }

    std::lock_guard<std::mutex> lock(mutex_);
    um_timers_[msgSeq] = mess_attr;
    HILOGI("add timer, msgSeq: %{public}lld", msgSeq);
    msgSeq++;
#endif
}

void TimerMgr::SubThingModelTimeroutHandler(union sigval sv)
{
    MessageTimerAttr* mess_attr = (MessageTimerAttr*)sv.sival_ptr;

    std::lock_guard<std::mutex> lock(mutex_);
    auto iter = um_timers_.find(mess_attr->msgSeq);
    if(iter != um_timers_.end()) {
        mess_attr->onResult(SubThingModelExecResult::SUB_MODEL_TIMEOUT, mess_attr->msgId, 
            mess_attr->svcId, mess_attr->devId, nullptr, 0);
        HILOGI("delete timer, msgSeq: %{public}llu", mess_attr->msgSeq);
        timer_delete(iter->second->timerId);
        delete iter->second;
    }
    um_timers_.erase(iter);
}

void TimerMgr::SubThingModelRecvDataHandler(const uint64_t msgSeq, const uint8_t *data, uint32_t len)
{
    std::lock_guard<std::mutex> lock(mutex_);
    auto iter = um_timers_.find(msgSeq);
    if(iter != um_timers_.end()) {
        iter->second->onResult(SubThingModelExecResult::SUB_MODEL_SUCC, iter->second->msgId, iter->second->svcId,
            iter->second->devId, (char*)data, len);
        timer_delete(iter->second->timerId);
        delete iter->second;
        HILOGI("delete timer, msgSeq: %{public}lld", msgSeq);
    }

    HILOGE("not find msgSeq");
}
}
}